package com.ruoyi.system.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import com.ruoyi.common.config.BigDataConfig;
import com.ruoyi.common.config.FtpConfig;
import com.ruoyi.common.core.domain.JSONObjectPro;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.page.Page;
import com.ruoyi.common.enums.comlbs.*;
import com.ruoyi.common.exception.BigDataException;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.http.BigDataResponse;
import com.ruoyi.common.utils.http.HttpRequest;
import com.ruoyi.system.domain.AlarmType;
import com.ruoyi.system.domain.EquipmentManagement;
import com.ruoyi.system.domain.request.reportstatistics.*;
import com.ruoyi.system.domain.vo.common.DeviceGps;
import com.ruoyi.system.domain.vo.reportstatistics.*;
import com.ruoyi.system.service.IAlarmTypeService;
import com.ruoyi.system.service.IEquipmentManagementService;
import com.ruoyi.system.service.IReportStatisticsService;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.utils.ComLbsUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 描述 统计报表Service实现类
 * 作者 ZhangPing
 * 创建时间 2023/8/17 15:34
 */
@Service
public class ReportStatisticsServiceImpl implements IReportStatisticsService {

    @Autowired
    private BigDataConfig bigDataConfig;
    @Autowired
    private FtpConfig ftpConfig;
    @Autowired
    private ISysDeptService deptService;
    @Autowired
    private IEquipmentManagementService equipmentManagementService;
    @Autowired
    private IAlarmTypeService alarmTypeService;

    /**
     * 多媒体数据分页列表
     *
     * @param param
     * @return
     */
    @Override
    public Page<Photo> photoList(ReportStatisticsListParam param) {
        //组装大数据接口参数
        JSONObjectPro bigDataParams = new JSONObjectPro()
                .put("pageIndex", param.getPageNum())
                .put("pageSize", param.getPageSize())
                .put("startTime", param.getStartTime())
                .put("endTime", param.getEndTime());
        //获取有权限的公司ID
        List<Long> deptIdList = deptService.selectPermissionDeptId(param.getCompanyId());
        bigDataParams.put("companyId", deptIdList);
        if (StringUtils.isNotEmpty(param.getNumberPlate())) {
            bigDataParams.put("numberPlate", Collections.singletonList(param.getNumberPlate()));
        }
        if (StringUtils.isNotEmpty(param.getDvo())) {
            bigDataParams.put("dvo", Collections.singletonList(param.getDvo()));
        }
        //远程调用接口
//        BigDataResponse<JSONObject> response = HttpRequest.postJsonBigData(bigDataConfig.getApiUrl() + "/photo/queryPage", bigDataParams, JSONObject.class);
//        if (!response.isSuccess()) throw new BigDataException();
//        JSONObject data = response.getData();
        JSONObject data =  new JSONObject();
        int total = data.getIntValue("totalCount");
        List<JSONObject> dataItems = data.getList("dataItems", JSONObject.class);
        if (ObjectUtils.isEmpty(dataItems)) return new Page<>();
        //封装数据
        List<Photo> resultList = dataItems.stream().map(item -> {
            Photo photo = new Photo()
                    .setCompanyName(item.get("companyName").toString())
                    .setDvo(item.get("dvo").toString())
                    .setNumberPlate(item.get("numberPlate").toString())
                    .setChannelId((int) item.get("channelId"));

            if (item.get("MediaPath") != null) {
                photo.setPictureUrl(ftpConfig.ftp2Http(item.get("MediaPath").toString()));
            }

            JSONObject gpsData = item.getJSONObject("gpsData");
            DeviceGps deviceGps = ComLbsUtils.bigDataGpsFormat(gpsData);
            photo.setTime(deviceGps.getGdt()).setLocation(deviceGps.getLocation());
            photo.setLat(deviceGps.getLat());
            photo.setLng(deviceGps.getLng());
            photo.setSpd(deviceGps.getSpd());
            photo.setSatelliteCount(deviceGps.getSatelliteCount());
            if ( ObjectUtils.isNotEmpty(item.get("driverInfo"))) {
                JSONObject driverJson = item.getJSONObject("driverInfo");
                photo.setDriverName(driverJson.getString("driverName").toString());
            }


            return photo;
        }).collect(Collectors.toList());
        return new Page<>(total, resultList);
    }


    /**
     * 车辆里程统计
     *
     * @param param
     * @return
     */
    @Override
    public Page<MileageStatistics> deviceMileageList(ReportStatisticsListParam param, boolean export) {
        //组装大数据接口参数
        JSONObjectPro bigDataParams = new JSONObjectPro()
                .put("page", param.getPageNum())
                .put("size", param.getPageSize())
                .put("startTime", DateUtils.parseToTimestamp(param.getStartTime() + " 00:00:00"))
                .put("endTime", DateUtils.parseToTimestamp(param.getEndTime() + " 23:59:59"));
        //获取有权限的公司ID
        if (param.getCompanyId() != null && param.getCompanyId() > 0) {
            List<Long> deptIdList = deptService.selectPermissionDeptId(param.getCompanyId());
            // 将List<Long>转换为逗号分隔的字符串（示例：1,2,3）
            String companyIdsStr = deptIdList.stream()
                    .map(String::valueOf)
                    .collect(Collectors.joining(","));
            bigDataParams.put("companyIds", companyIdsStr);
        }

        if (StringUtils.isNotEmpty(param.getNumberPlate())) {
            // 直接传递原始值，让HTTP库自动编码
            bigDataParams.put("numberPlate", param.getNumberPlate());
        }

        if (StringUtils.isNotEmpty(param.getDvo())) {
            bigDataParams.put("dvo", Collections.singletonList(param.getDvo()));
        }
        //远程调用接口
        String url = export ? "/ads/day/mileage/list" : "/ads/day/mileage/page";
        BigDataResponse response = HttpRequest.getBigDataNoEncode(bigDataConfig.getApiUrl() + url, bigDataParams, JSONObject.class);
        if (!response.isSuccess()) throw new BigDataException();
        // 提取分页数据
        BigDataResponse.PageData<JSONObject> pageData = response.getData();
        int total = pageData.getTotalCount();
        List<JSONObject> dataItems = pageData.getDataItems();

        // 处理空数据
        if (ObjectUtils.isEmpty(dataItems)) {
            return new Page<>();
        }

        Map<Long, String> deptMap = deptService.selectDeptList(new SysDept()).stream().collect(Collectors.toMap(SysDept::getDeptId, SysDept::getShortName));
        //封装数据
        List<MileageStatistics> resultList = dataItems.stream().map(item -> {
            Long companyId = Long.parseLong(item.getString("companyId"));
            MileageStatistics mileageStatistics = new MileageStatistics()
                    .setCompanyId(companyId)
                    .setCompanyName(deptMap.getOrDefault(companyId, ""))
                    .setCompanyName(deptMap.getOrDefault(companyId, ""))
                    .setDvo(item.getString("dvo"))
                    .setMileage((int)(item.getDouble("kilometer")*1000.0))
                    .setNumberPlate(item.getString("numberPlate"))
                    .setDriverMinutes(item.getDouble("driverMinutes"))
                    .setKilometer(item.getDouble("kilometer"));
            if (item.get("staDay") != null) mileageStatistics.setDay(new Date(item.getLong("staDay")));
            return mileageStatistics;
        }).collect(Collectors.toList());
        return new Page<>(total, resultList);
    }

    /**
     * 车辆里程统计汇总导出
     *
     * @param param
     * @return
     */
    @Override
    public List<MileageStatistics> deviceMileageListSummaryExport(ReportStatisticsListParam param) {
        Page<MileageStatistics> page = deviceMileageList(param, true);
        //按车牌号汇总导出
        List<MileageStatistics> resultList = new ArrayList<>();
        if (ObjectUtils.isNotEmpty(page.getList())) {
            page.getList().stream().collect(Collectors.groupingBy(MileageStatistics::getNumberPlate)).forEach((numberPlate, list) -> {
                MileageStatistics item = list.get(0)
                        .setDay(null)
//                        .setMileage(list.stream().mapToInt(MileageStatistics::getMileage).sum())
//                        .setOilConsumption(ComLbsUtils.round45(list.stream().mapToDouble(MileageStatistics::getOilConsumption).sum()))
                        .setDriverMinutes(ComLbsUtils.round45(list.stream().mapToDouble(MileageStatistics::getDriverMinutes).sum()))
                        .setKilometer(ComLbsUtils.round45(list.stream().mapToDouble(MileageStatistics::getKilometer).sum()));
                resultList.add(item);
            });
        }
        return resultList;
    }

    /**
     * 车辆里程明细
     *
     * @param param
     * @return
     */
    @Override
    public Page<MileageStatistics> deviceMileageDetailList(ReportStatisticsListParam param, boolean export) {
        //组装大数据接口参数
        JSONObjectPro bigDataParams = new JSONObjectPro()
                .put("page", param.getPageNum())
                .put("size", param.getPageSize())
                .put("startTime", DateUtils.parseToTimestamp(param.getStartTime()))
                .put("endTime", DateUtils.parseToTimestamp(param.getEndTime()));
        //获取有权限的公司ID
        if (param.getCompanyId() != null && param.getCompanyId() > 0) {
            List<Long> deptIdList = deptService.selectPermissionDeptId(param.getCompanyId());
            // 将List<Long>转换为逗号分隔的字符串（示例：1,2,3）
            String companyIdsStr = deptIdList.stream()
                    .map(String::valueOf)
                    .collect(Collectors.joining(","));
            bigDataParams.put("companyIds", companyIdsStr);
        }

        if (StringUtils.isNotEmpty(param.getNumberPlate())) {
            bigDataParams.put("numberPlate",param.getNumberPlate());
        }
        //远程调用接口
        String url = export ? "/dwd/mileage/hour/list" : "/dwd/mileage/hour/page";
        BigDataResponse response = HttpRequest.getBigDataNoEncode(bigDataConfig.getApiUrl() + url, bigDataParams, JSONObject.class);
        if (!response.isSuccess()) throw new BigDataException();

        // 提取分页数据
        BigDataResponse.PageData<JSONObject> pageData = response.getData();
        int total = pageData.getTotalCount();
        List<JSONObject> dataItems = pageData.getDataItems();

        // 处理空数据
        if (ObjectUtils.isEmpty(dataItems)) {
            return new Page<>();
        }
        Map<Long, String> deptMap = deptService.selectDeptList(new SysDept()).stream().collect(Collectors.toMap(SysDept::getDeptId, SysDept::getShortName));
        //封装数据
        List<MileageStatistics> resultList = dataItems.stream().map(item -> {
            Long companyId = Long.parseLong(item.getString("companyId"));
            MileageStatistics mileageStatistics = new MileageStatistics()
                    .setCompanyId(companyId)
                    .setCompanyName(deptMap.getOrDefault(companyId, ""))
                    .setDvo(item.getString("dvo"))
                    .setNumberPlate(item.getString("numberPlate"))
                    .setDriverMinutes(item.getDouble("driverMinutes"))
                    .setKilometer(item.getDouble("kilometer"));
            if (item.get("staHour") != null) mileageStatistics.setDay(new Date(item.getLong("staHour")));
            return mileageStatistics;
        }).collect(Collectors.toList());


        return new Page<>(total, resultList);
    }

    /**
     * 历史轨迹明细
     *
     * @param param
     * @return
     */
    @Override
    public Page<Trajectory> trajectoryHistoryList(TrajectoryParam param, boolean export) {
        //组装大数据接口参数
        JSONObjectPro bigDataParams = new JSONObjectPro()
                .put("dvo", param.getDvo())
                .put("spd", param.getSpeed())
                .put("page", param.getPageNum())
                .put("size", param.getPageSize())
                .put("startTime", DateUtils.parseToTimestamp(param.getStartTime()))
                .put("endTime", DateUtils.parseToTimestamp(param.getEndTime()));

        //判断查询设备是不是在权限范围内
        EquipmentManagement equipment = equipmentManagementService.getByDeviceId(param.getDvo());
        Map<Long, String> deptMap = deptService.selectDeptList(new SysDept()).stream().collect(Collectors.toMap(SysDept::getDeptId, SysDept::getShortName));
        if (equipment == null || !deptMap.keySet().contains(equipment.getCompanyId())) {
            throw new ServiceException("设备不存在或无设备权限");
        }
        //远程调用接口
        String url = export ? "/dws/gps/list" : "/dws/gps/page";
        BigDataResponse response = HttpRequest.getBigDataNoEncode(bigDataConfig.getApiUrl() + url, bigDataParams, JSONObject.class);
        if (!response.isSuccess()) throw new BigDataException();
        // 提取分页数据
        BigDataResponse.PageData<JSONObject> pageData = response.getData();
        int total = pageData.getTotalCount();
        List<JSONObject> dataItems = pageData.getDataItems();

        // 处理空数据
        if (ObjectUtils.isEmpty(dataItems)) {
            return new Page<>();
        }
        //封装数据
        List<Trajectory> resultList = dataItems.stream().map(item -> {
            Long companyId = Long.parseLong(item.getString("companyId"));
            JSONObject popJson = item.getJSONObject("pop");
            Trajectory trajectory = new Trajectory()
                    .setCompanyName(deptMap.getOrDefault(companyId, ""))
                    .setDvo(item.getString("dvo"))
                    .setSatelliteCount(popJson == null ? 0 : popJson.getIntValue(PopMapEnum.SatelliteCount.getCode().toString()))
                    .setNumberPlate(item.getString("numberPlate"))
                    .setSpeed(item.getIntValue("spd"))
                    .setLng(item.getDoubleValue("lng"))
                    .setLat(item.getDoubleValue("lat"));
            if (item.get("address") != null) {
                trajectory.setLocation(item.getString("address"));
            }
            if (item.get("gte") != null) {
                trajectory.setTime(new Date(item.getLongValue("gte")));
            }

            //高程
            if (item.get("hgt") != null) {
                trajectory.setHgt(item.getIntValue("hgt"));
            }
            return trajectory;
        }).collect(Collectors.toList());

        return new Page<>(total, resultList);
    }

    @Override
    public Page<DeviceOnline> deviceOnlineList(ReportStatisticsListParam param, boolean export) {
        //组装大数据接口参数
        JSONObjectPro bigDataParams = new JSONObjectPro()
                .put("status", "1")
                .put("page", param.getPageNum())
                .put("size", param.getPageSize())
                .put("startTime", DateUtils.parseToTimestamp(param.getStartTime()))
                .put("endTime", DateUtils.parseToTimestamp(DateUtils.addDay(param.getEndTime(), 1)));

        //获取有权限的公司ID
        if (param.getCompanyId() != null && param.getCompanyId() > 0) {
            List<Long> deptIdList = deptService.selectPermissionDeptId(param.getCompanyId());
            // 将List<Long>转换为逗号分隔的字符串（示例：1,2,3）
            String companyIdsStr = deptIdList.stream()
                    .map(String::valueOf)
                    .collect(Collectors.joining(","));
            bigDataParams.put("companyIds", companyIdsStr);
        }
        if (StringUtils.isNotEmpty(param.getNumberPlate())) {
            bigDataParams.put("numberPlate",param.getNumberPlate());
        }
        if (StringUtils.isNotEmpty(param.getDvo())) {
            bigDataParams.put("dvo",param.getDvo());
        }

        //远程调用接口
        String url = export ? "/ads/day/online/list" : "/ads/day/online/page";
        BigDataResponse response = HttpRequest.getBigDataNoEncode(bigDataConfig.getApiUrl() + url, bigDataParams, JSONObject.class);
        if (!response.isSuccess()) throw new BigDataException();

        // 提取分页数据
        BigDataResponse.PageData<JSONObject> pageData = response.getData();
        int total = pageData.getTotalCount();
        List<JSONObject> dataItems = pageData.getDataItems();

        // 处理空数据
        if (ObjectUtils.isEmpty(dataItems)) {
            return new Page<>();
        }

        Map<Long, String> deptMap = deptService.selectDeptList(new SysDept()).stream().collect(Collectors.toMap(SysDept::getDeptId, SysDept::getShortName));
        //封装数据
        List<DeviceOnline> resultList = dataItems.stream().map(item -> {
            Long companyId = Long.parseLong(item.getString("companyId"));
            DeviceOnline deviceOnline = new DeviceOnline()
                    .setCompanyName(deptMap.getOrDefault(companyId, ""))
                    .setCompanyShortName(deptMap.getOrDefault(companyId, ""))
                    .setDvo(item.getString("dvo"))
                    .setNumberPlate(item.getString("numberPlate"))
                    .setOnlineMinutes(DateUtils.timeDistance((long) (item.getDoubleValue("onlineMinutes") * 60 * 1000)));
            if (item.get("staDay") != null) {
                deviceOnline.setDay(new Date(Long.parseLong(item.getString("staDay"))));
            }
            if (item.get("startTime") != null) {
                deviceOnline.setStartTime(new Date(Long.parseLong(item.getString("startTime"))));
            }
            if (item.get("endTime") != null) {
                deviceOnline.setEndTime(new Date(Long.parseLong(item.getString("endTime"))));
            }
            return deviceOnline;
        }).collect(Collectors.toList());
        return new Page<>(total, resultList);
    }

    /**
     * 报警统计
     *
     * @return
     */
    @Override
    public Page<AlarmStatistics> deviceAlarmList(DeviceAlarmListParam param, boolean export) {
        //组装大数据接口参数
        JSONObjectPro bigDataParams = new JSONObjectPro()
                .put("page", param.getPageNum())
                .put("size", param.getPageSize())
                .put("startTime", DateUtils.parseToTimestamp(param.getStartTime()))
                .put("endTime", DateUtils.parseToTimestamp(DateUtils.addDay(param.getEndTime(), 1)));

        //获取有权限的公司ID
        if (param.getCompanyId() != null && param.getCompanyId() > 0) {
            List<Long> deptIdList = deptService.selectPermissionDeptId(param.getCompanyId());
            // 将List<Long>转换为逗号分隔的字符串（示例：1,2,3）
            String companyIdsStr = deptIdList.stream()
                    .map(String::valueOf)
                    .collect(Collectors.joining(","));
            bigDataParams.put("companyIds", companyIdsStr);
        }

        if (param.getSource() != null) {
            bigDataParams.put("src", param.getSource());
        }

//        //获取指定公司的告警类型Map
//        Map<Integer, AlarmType> alarmTypeMap = alarmTypeService.getUserAlarmTypeMap();
//        //封装告警类型集合参数
//        List<Integer> alarmTypes = new ArrayList<>(alarmTypeMap.keySet());
//        if (param.getType() != null) {
//            alarmTypes.retainAll(Collections.singletonList(param.getType()));
//        }

        if (param.getType() != null) {
            bigDataParams.put("alarmTypes", param.getType());
        }

//        if (CollectionUtils.isEmpty(alarmTypes)) {
//            return new Page<>(0, new ArrayList<>());
//        }else {
//            bigDataParams.put("alarmTypes", alarmTypes);
//        }

        if (StringUtils.isNotEmpty(param.getNumberPlate())) {
            bigDataParams.put("numberPlate",param.getNumberPlate());
        }

        //远程调用接口
        String url = export ? "/dwd/device/alarm/sta/list" : "/dwd/device/alarm/sta/page";
        BigDataResponse response = HttpRequest.getBigDataNoEncode(bigDataConfig.getApiUrl() + url, bigDataParams, JSONObject.class);
        if (!response.isSuccess()) throw new BigDataException();

        // 提取分页数据
        BigDataResponse.PageData<JSONObject> pageData = response.getData();
        int total = pageData.getTotalCount();
        List<JSONObject> dataItems = pageData.getDataItems();

        // 处理空数据
        if (ObjectUtils.isEmpty(dataItems)) {
            return new Page<>();
        }

        Map<Long, String> deptMap = deptService.selectDeptList(new SysDept()).stream().collect(Collectors.toMap(SysDept::getDeptId, SysDept::getShortName));
        //封装数据
        List<AlarmStatistics> resultList = dataItems.stream().map(item -> {
            Long companyId =item.getLong("companyId");
            AlarmStatistics statistics = new AlarmStatistics()
                    .setType(item.getInteger("alarmType"))
                    .setCompanyId(item.getLong("companyId"))
                    .setCompanyName(deptMap.getOrDefault(companyId, ""))
                    .setNumberPlate( item.getString("numberPlate"))
                    .setDeviceId(item.getString("dvo"))
                    .setCount( item.getInteger("alarmCount"))
                    .setMinutes( item.getDouble("alarmMinutes"))
                    .setStartTime( new Date(item.getLong("startTime")))
                    .setEndTime( new Date(item.getLong("endTime")))
                    .setSource( item.getInteger("src"))
                    .setSourceName(DictUtils.getDictLabel("source",  item.getInteger("src")));
            return statistics;
        }).collect(Collectors.toList());
        return new Page<>(total, resultList);
    }

    /**
     * 报警明细
     *
     * @param param
     * @return
     */
    @Override
    public Page<AlarmDetail> deviceAlarmDetailList(DeviceAlarmListParam param, boolean export) {
        //组装大数据接口参数
        JSONObjectPro bigDataParams = new JSONObjectPro()
                .put("page", param.getPageNum())
                .put("size", param.getPageSize())
                .put("startTime", DateUtils.parseToTimestamp(param.getStartTime()))
                .put("endTime", DateUtils.parseToTimestamp(param.getEndTime()));

        //获取指定公司的告警类型Map
        Map<Integer, AlarmType> alarmTypeMap = alarmTypeService.getUserAlarmTypeMap();
//        //封装告警类型集合参数
        List<Integer> alarmTypes = new ArrayList<>(alarmTypeMap.keySet());
//        if (param.getLevel() != null) {
//            alarmTypes.retainAll(alarmTypeService.alarmLevelToAlarmTypeList(param.getLevel()));
//        }
        if (param.getType() != null) {
            alarmTypes.retainAll(Collections.singletonList(param.getType()));
        }
        if (CollectionUtils.isEmpty(alarmTypes)) {
            return new Page<>(0, new ArrayList<>());
        }
        bigDataParams.put("alarmTypes", alarmTypes);

         //获取有权限的公司ID
        if (param.getCompanyId() != null && param.getCompanyId() > 0) {
            List<Long> deptIdList = deptService.selectPermissionDeptId(param.getCompanyId());
            // 将List<Long>转换为逗号分隔的字符串（示例：1,2,3）
            String companyIdsStr = deptIdList.stream()
                    .map(String::valueOf)
                    .collect(Collectors.joining(","));
            bigDataParams.put("companyIds", companyIdsStr);
        }

        if (StringUtils.isNotEmpty(param.getNumberPlate())) {
            bigDataParams.put("numberPlate", param.getNumberPlate());
        }
        if (param.getSource() != null) {
            bigDataParams.put("src", param.getSource());
        }
        //远程调用接口
        String url = export ? "/dwd/device/alarm/list" : "/dwd/device/alarm/page";
        BigDataResponse response = HttpRequest.getBigDataNoEncode(bigDataConfig.getApiUrl() + url, bigDataParams, JSONObject.class);
        if (!response.isSuccess()) throw new BigDataException();

        // 提取分页数据
        BigDataResponse.PageData<JSONObject> pageData = response.getData();
        int total = pageData.getTotalCount();
        List<JSONObject> dataItems = pageData.getDataItems();

        // 处理空数据
        if (ObjectUtils.isEmpty(dataItems)) {
            return new Page<>();
        }

        Map<Long, String> deptMap = deptService.selectDeptList(new SysDept()).stream().collect(Collectors.toMap(SysDept::getDeptId, SysDept::getShortName));

        List<AlarmDetail> resultList = dataItems.stream().map(item -> {
            Long companyId = Long.parseLong(item.getString("companyId"));
            AlarmDetail detail = new AlarmDetail()
                    .setCompanyId(item.getLong("companyId"))
                    .setCompanyName(deptMap.getOrDefault(companyId, ""))
                    .setNumberPlate(item.getString("numberPlate"))
                    .setDeviceId(item.getString("dvo"))
                    .setSpeed(item.getIntValue("spd"))
                    .setLng(item.getDoubleValue("lng"))
                    .setLat(item.getDoubleValue("lat"))
                    .setSource(item.getIntValue("src"))
                    .setSourceName(DictUtils.getDictLabel("source", item.getIntValue("src")));
            return detail;
        }).collect(Collectors.toList());
        return new Page<>(total, resultList);
    }

    /**
     * 公司整点上线率
     *
     * @param param
     * @return
     */
    @Override
    public Page<CompanyHourlyOnlineRate> companyHourlyOnlineRate(CompanyHourlyOnlineRateParam param, boolean export) {
        //组装大数据接口参数
        JSONObjectPro bigDataParams = new JSONObjectPro()
                .put("page", param.getPageNum())
                .put("size", param.getPageSize())
                .put("startTime", DateUtils.parseToTimestamp(param.getStartTime()))
                .put("endTime", DateUtils.parseToTimestamp(DateUtils.addDay(param.getEndTime(), 1)));

        //获取有权限的公司ID
        if (param.getCompanyId() != null && param.getCompanyId() > 0) {
            List<Long> deptIdList = deptService.selectPermissionDeptId(param.getCompanyId());
            // 将List<Long>转换为逗号分隔的字符串（示例：1,2,3）
            String companyIdsStr = deptIdList.stream()
                    .map(String::valueOf)
                    .collect(Collectors.joining(","));
            bigDataParams.put("companyIds", companyIdsStr);
        }

        //远程调用接口
        String url = export ? "/ads/company/rate/list" : "/ads/company/rate/page";
        BigDataResponse response = HttpRequest.getBigDataNoEncode(bigDataConfig.getApiUrl() + url, bigDataParams, JSONObject.class);
        if (!response.isSuccess()) throw new BigDataException();

        // 提取分页数据
        BigDataResponse.PageData<JSONObject> pageData = response.getData();
        int total = pageData.getTotalCount();
        List<JSONObject> dataItems = pageData.getDataItems();

        // 处理空数据
        if (ObjectUtils.isEmpty(dataItems)) {
            return new Page<>();
        }

        Map<Long, String> deptMap = deptService.selectDeptList(new SysDept()).stream().collect(Collectors.toMap(SysDept::getDeptId, SysDept::getShortName));

        List<CompanyHourlyOnlineRate> resultList = dataItems.stream().map(item -> {
            Long companyId = Long.parseLong(item.get("companyId").toString());
            String companyName = ObjectUtils.isEmpty(deptMap.get(companyId)) ? "" : deptMap.get(companyId);
            CompanyHourlyOnlineRate onlineRate = new CompanyHourlyOnlineRate()
                    .setNetworkCar(item.getIntValue("allNum"))
                    .setOnlineCar(item.getIntValue("onlineNum"))
                    .setOnlineRate(item.getString("onlineRate"))
                    .setCompanyId(companyId)
                    .setCompanyName(companyName)
                    .setCompanyShortName(companyName);
            if (item.get("staDay") != null) {
                onlineRate.setTime(new Date(item.getLong("staDay")));
            }

            return onlineRate;
        }).collect(Collectors.toList());
        return new Page<>(total, resultList);
    }

    /**
     * 公司整点上线率汇总导出
     *
     * @param param
     * @return
     */
    @Override
    public List<CompanyHourlyOnlineRateSummary> companyHourlyOnlineRateSummaryExport(CompanyHourlyOnlineRateParam param) {
        //组装大数据接口参数
        JSONObjectPro bigDataParams = new JSONObjectPro()
                .put("startTime", DateUtils.parseToTimestamp(param.getStartTime()))
                .put("endTime", DateUtils.parseToTimestamp(param.getEndTime()));

        //获取有权限的公司ID
        if (param.getCompanyId() != null && param.getCompanyId() > 0) {
            List<Long> deptIdList = deptService.selectPermissionDeptId(param.getCompanyId());
            // 将List<Long>转换为逗号分隔的字符串（示例：1,2,3）
            String companyIdsStr = deptIdList.stream()
                    .map(String::valueOf)
                    .collect(Collectors.joining(","));
            bigDataParams.put("companyIds", companyIdsStr);
        }
        //远程调用接口
        BigDataResponse response = HttpRequest.getBigDataNoEncode(bigDataConfig.getApiUrl() + "/ads/company/rate/list", bigDataParams,JSONObject.class);
        if (!response.isSuccess()) throw new BigDataException();
        // 提取分页数据
        BigDataResponse.PageData<JSONObject> pageData = response.getData();
        List<JSONObject> dataItems = pageData.getDataItems();
        // 处理空数据
        if (ObjectUtils.isEmpty(dataItems)) {
            return  new ArrayList<>();
        }

        Map<Long, String> deptMap = deptService.selectDeptList(new SysDept()).stream().collect(Collectors.toMap(SysDept::getDeptId, SysDept::getShortName));
        List<CompanyHourlyOnlineRate> dataList = dataItems.stream().map(item -> {
            Long companyId = Long.parseLong(item.get("companyId").toString());
            String companyName = deptMap.getOrDefault(companyId, "");
            CompanyHourlyOnlineRate onlineRate = new CompanyHourlyOnlineRate()
                    .setNetworkCar(item.getIntValue("allNum"))
                    .setOnlineCar(item.getIntValue("onlineNum"))
                    .setOnlineRate(item.getString("onlineRate"))
                    .setCompanyId(companyId)
                    .setCompanyName(companyName)
                    .setCompanyShortName(companyName);
            if (item.get("staDay") != null) {
                onlineRate.setTime(new Date(item.getLong("staDay")));
            }
            return onlineRate;
        }).collect(Collectors.toList());
        Map<Long, List<CompanyHourlyOnlineRate>> companyMap = dataList.stream().collect(Collectors.groupingBy(CompanyHourlyOnlineRate::getCompanyId));
        List<CompanyHourlyOnlineRateSummary> resultList = new ArrayList<>();
        for (Long companyId : companyMap.keySet()) {
            List<CompanyHourlyOnlineRate> list = companyMap.get(companyId);
            CompanyHourlyOnlineRate item = list.get(0);
            int sum = list.stream().mapToInt(i -> Integer.parseInt(i.getOnlineRate().replace("%", ""))).sum();
            resultList.add(new CompanyHourlyOnlineRateSummary(item.getCompanyName(), ComLbsUtils.round45(sum * 1.0 / list.size()) + "%"));
        }
        return resultList;
    }

    /**
     * 公司整点上线率详情
     *
     * @param param
     * @return
     */
    @Override
    public List<CompanyHourlyOnlineDetail> companyHourlyOnlineDetail(CompanyHourlyOnlineDetailParam param) {
        //远程调用接口
        JSONObjectPro bigDataParams = new JSONObjectPro()
                .put("numberPlate", param.getNumberPlate())
                .put("companyIds", param.getCompanyId())
                .put("startTime", DateUtils.parseToTimestamp(param.getStartTime()))
                .put("endTime", DateUtils.parseToTimestamp(param.getEndTime()));

        //远程调用接口
        BigDataResponse response = HttpRequest.getBigDataNoEncode(bigDataConfig.getApiUrl() + "/ads/day/online/list", bigDataParams,JSONObject.class);
        if (!response.isSuccess()) throw new BigDataException();
        // 提取分页数据
        BigDataResponse.PageData<JSONObject> pageData = response.getData();
        List<JSONObject> dataItems = pageData.getDataItems();
        // 处理空数据
        if (ObjectUtils.isEmpty(dataItems)) {
            return  new ArrayList<>();
        }

        Map<Long, String> deptMap = deptService.selectDeptList(new SysDept()).stream().collect(Collectors.toMap(SysDept::getDeptId, SysDept::getShortName));

        List<CompanyHourlyOnlineDetail> resultList = dataItems.stream().map(item -> {
            Long companyId = Long.parseLong(item.get("companyId").toString());
            String companyName = ObjectUtils.isEmpty(deptMap.get(companyId)) ? "" : deptMap.get(companyId);
            CompanyHourlyOnlineDetail onlineRate = new CompanyHourlyOnlineDetail()
                    .setOnlineStatus(item.getInteger("status"))
                    .setNumberPlate(item.getString("numberPlate"))
                    .setCompanyName(companyName);
            if (item.get("staDay") != null) {
                onlineRate.setTime(new Date(item.getLong("staDay")));
            }
            return onlineRate;
        })// 新增排序逻辑：按onlineStatus字段降序排列
        .sorted(Comparator.comparingInt(CompanyHourlyOnlineDetail::getOnlineStatus).reversed())
        .collect(Collectors.toList());
        return resultList;
    }

    /**
     * 车辆状态统计列表
     *
     * @param param
     * @return
     */
    @Override
    public Page<DeviceStatusStatistics> deviceStatusStatisticsList(StatusStatisticsListParam param, boolean export) {
        JSONObjectPro bigDataParams = new JSONObjectPro()
                .put("page", param.getPageNum())
                .put("size", param.getPageSize())
                .put("status", param.getStatus());

    //获取有权限的公司ID
        if (param.getCompanyId() != null && param.getCompanyId() > 0) {
            List<Long> deptIdList = deptService.selectPermissionDeptId(param.getCompanyId());
            // 将List<Long>转换为逗号分隔的字符串（示例：1,2,3）
            String companyIdsStr = deptIdList.stream()
                    .map(String::valueOf)
                    .collect(Collectors.joining(","));
            bigDataParams.put("companyIds", companyIdsStr);
        }

        if (StringUtils.isNotEmpty(param.getNumberPlate())) {
            bigDataParams.put("numberPlate", param.getNumberPlate());
        }
        //远程调用接口
        String url = export ? "/dws/device/status/list" : "/dws/device/status/page";
        BigDataResponse response = HttpRequest.getBigDataNoEncode(bigDataConfig.getApiUrl() + url, bigDataParams, JSONObject.class);
        if (!response.isSuccess()) throw new BigDataException();

        // 提取分页数据
        BigDataResponse.PageData<JSONObject> pageData = response.getData();
        int total = pageData.getTotalCount();
        List<JSONObject> dataItems = pageData.getDataItems();

        // 处理空数据
        if (ObjectUtils.isEmpty(dataItems)) {
            return new Page<>();
        }

        Map<Long, String> deptMap = deptService.selectDeptList(new SysDept()).stream().collect(Collectors.toMap(SysDept::getDeptId, SysDept::getShortName));



        //组装数据
        List<DeviceStatusStatistics> resultList = dataItems.stream().map(item -> {
            Long companyId = item.getLongValue("companyId");
            //1:'入网设备' 2:'在线设备' 3:'离线设备' 4:'从未上线' 5:'7天未上线' 6:'30天未上线'
            //0：行驶  1.停止  2.熄火  3：定位失败  4：离线  5：未定位  6：在线
            String vehicleStatus = "未知状态";
            if (param.getStatus() != null && param.getStatus()>0) {
                if (param.getStatus() == 3 || param.getStatus() == 5 || param.getStatus() == 6){
                    vehicleStatus = VehicleStatusEnum.getTextByCode(4);//
                }else if(param.getStatus() == 4){
                    vehicleStatus = VehicleStatusEnum.getTextByCode(5);
                }else {
                    vehicleStatus = VehicleStatusEnum.getTextByCode(item.getIntValue("status"));
                }
            }
            DeviceStatusStatistics statistics = new DeviceStatusStatistics()
                    .setKilometer(item.getDoubleValue("totalMile")/1000.0)
                    .setNumberPlate(item.getString("numberPlate"))
                    .setSpd(item.getIntValue("spd"))
                    .setMie(item.getIntValue("totalMile"))
                    .setAddress(item.getString("address"))
                    .setCompanyId(companyId)
                    .setCompanyName(deptMap.getOrDefault(companyId, ""))
                    .setVehicleStatus(vehicleStatus);//0：行驶  1.停止  2.熄火  3：定位失败  4：离线  5：未定位  6：在线
            if (ObjectUtils.isNotEmpty(item.get("fixedTime"))) {
                statistics.setGdt(new Date(item.getLong("fixedTime")));
            }
            return statistics;
        }).collect(Collectors.toList());
        return new Page<>(total, resultList);
    }

    /**
     * 人脸识别统计列表
     *
     * @param param
     * @param export
     * @return
     */
    public Page<PersonFaceResultStatistics> personFaceResultList(PersonFaceParam param, boolean export) {
        //获取有权限的公司ID
//        List<Long> deptIdList = deptService.selectPermissionDeptId(param.getCompanyId());

        JSONObjectPro httpJson = new JSONObjectPro()
//                .put("companyIds", deptIdList)
                .put("startTime", param.getStartTime())
                .put("endTime", param.getEndTime());
        if (!export) {
            httpJson.put("pageIndex", param.getPageNum()).put("pageSize", param.getPageSize());
        }
        if (ObjectUtils.isNotEmpty(param.getNumberPlate())) httpJson.put("numberPlate", param.getNumberPlate());
        if (ObjectUtils.isNotEmpty(param.getResult())) httpJson.put("result", param.getResult());

        //调用大数据的接口获取数据
//        BigDataResponse<List<JSONObject>> response = HttpRequest.postJsonBigData(bigDataConfig.getApiUrl() + "/faceRecognition/queryFaceRecognition",
//                httpJson, new TypeReference<List<JSONObject>>() {
//                }.getType());
//        if (!response.isSuccess()) throw new BigDataException();
        int total = 0;
        List<PersonFaceResultStatistics> resultList = new ArrayList<>();
//        List<JSONObject> detail = response.getData();
//        Map<Long, String> deptMap = deptService.selectDeptList(new SysDept()).stream().collect(Collectors.toMap(SysDept::getDeptId, SysDept::getDeptName));
//        //封装数据
//        int total = response.getTotalCount();
//        List<PersonFaceResultStatistics> resultList = detail.stream().map(data -> {
//            PersonFaceResultStatistics result = new PersonFaceResultStatistics();
//            result.setDriverName(data.get("driverName").toString());
//            result.setNumberPlate(data.get("numberPlate").toString());
//            result.setResult((Integer) data.get("result"));
//            long compId = Long.parseLong(data.get("companyId").toString());
//            String shortName = deptMap.get(compId);
//            if (shortName != null) {
//                result.setComapnyShortName(shortName);
//            } else {
//                result.setComapnyShortName("");
//            }
//            String resultStr = DictUtils.getDictLabel(DataDictTypeEnum.SUCCESS_FAIL.getText(), data.get("result").toString());
//            result.setResultStr(resultStr);
//            if (data.get("pte") != null) {
//                Date time = DateUtils.parseDate(data.get("pte").toString());
//                result.setTime(time);
//            }
//            String id = data.get("companyId").toString();
//            if (deptMap.get(Long.parseLong(id)) != null) {
//                result.setCompanyName(deptMap.get(Long.parseLong(id)));
//            } else {
//                result.setCompanyName("");
//            }
//            result.setPicture(ftpConfig.ftp2Http(data.get("path").toString()));
//            return result;
//        }).collect(Collectors.toList());
        return new Page<>(total, resultList);
    }
}
